/**
 * NetworkUtil.java
 */
package com.mht2017.common.utils;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

/**
 * @author yutong.xiao
 * @date 2017年8月23日 下午2:43:54
 */
public class NetworkUtil {

	/** 获取本机的所有ipv4的地址（除了回环地址） */
	public static List<String> getAllIpv4ExcludeLoopback() {
		List<String> ips = new LinkedList<>();
		try {
			Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
			while (networkInterfaces.hasMoreElements()) {
				NetworkInterface networkInterface = networkInterfaces.nextElement();
				Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
				while (inetAddresses.hasMoreElements()) {
					InetAddress inetAddress = inetAddresses.nextElement();
					if (inetAddress instanceof Inet4Address && InetAddress.getLoopbackAddress().equals(inetAddress) == false) {
						System.out.println(String.format("%s: '%s'", networkInterface.getDisplayName(), inetAddress.getHostAddress()));
						ips.add(inetAddress.getHostAddress());
					}
				}
			}
		} catch (SocketException e) {
			e.printStackTrace();
		}
		return ips;
	}

	/**
	 * 根据pattern获取本机ipv4列表的第一个ip，如果没有匹配到，则返回null
	 *
	 * @param pattern
	 *            正则
	 * @return
	 */
	public static String getFirstIpv4ByPattern(String pattern) {
		return getOneIpv4ByPattern(pattern, false);
	}

	/**
	 * 根据pattern获取一个ipv4，如果刚好匹配到1个ip，则正常返回，否则抛出异常
	 *
	 * @param pattern
	 *            正则
	 * @return
	 * @throws TooManyIpException
	 * @throws NoIpException
	 */
	public static String getOneIpv4ByPattern(String pattern) throws NoIpException, TooManyIpException {
		return getOneIpv4ByPattern(pattern, true);
	}

	private static String getOneIpv4ByPattern(String pattern, boolean exceptionIfMany) throws NoIpException, TooManyIpException {
		if (StringUtils.isEmpty(pattern)) {
			return null;
		}

		String regex = pattern.replaceAll("\\.\\*|\\*", ".*").replaceAll("\\.\\?|\\?", ".?");
		Pattern regexPattern = Pattern.compile(regex);
		List<String> allIpv4ExcludeLoopback = getAllIpv4ExcludeLoopback();
		if (CollectionUtils.isNotEmpty(allIpv4ExcludeLoopback)) {
			List<String> matchIps = new LinkedList<>();
			for (String ipv4 : allIpv4ExcludeLoopback) {
				if (regexPattern.matcher(ipv4).matches()) {
					matchIps.add(ipv4);
				}
			}
			if (matchIps.size() == 1) {
				return matchIps.get(0);
			} else if (exceptionIfMany) {
				throw matchIps.isEmpty() ? new NoIpException() : new TooManyIpException(StringUtils.join(matchIps, ','));
			} else {
				return matchIps.isEmpty() == false ? matchIps.get(0) : null;
			}
		}
		return null;
	}

	public static class TooManyIpException extends RuntimeException {

		private static final long serialVersionUID = 1L;

		public TooManyIpException(String message) {
			super(message);
		}

	}

	public static class NoIpException extends RuntimeException {

		private static final long serialVersionUID = 1L;

	}

}
